from .html import (
    svg as tagic_svg,
    path as tagic_path,
)

from typing import Any, Callable, Sequence
from functools import reduce


snake_case_to_kebab = lambda x: x.replace("_", "-")
kebab_case_to_snake = lambda x: x.replace("-", "_")
drop_ends_underline = lambda x: x[:-1] if x and x[-1] == "_" else x


def _object_custom_attrs(o: object) -> Sequence[str]:
    return filter(
        lambda x: x
        and not x.startswith("__")
        and not x.endswith("__")
        and not isinstance(getattr(o, x), Callable),  # 不包含函数
        dir(o),
    )


def _user_define_properties_dict(o: object) -> dict[str, Any]:
    user_properties = _object_custom_attrs(o)

    def merge_dict(a, b):
        t = {f"{b}": getattr(o, b)}
        return a | t

    return reduce(merge_dict, user_properties, {})


def _change_key_case(d: dict[str, Any], changes: Sequence[Callable[[str], str]]):
    def pipeline(v, fn):
        return fn(v)

    del_keys = []
    new_items = []
    for [key, value] in d.items():
        new_key = reduce(pipeline, changes, key)
        if key != new_key:
            new_items.append((new_key, value))
            del_keys.append(key)
    for key in del_keys:
        del d[key]
    for [k, v] in new_items:
        d[k] = v
    return d


class PythonIdentifier:
    """符合Python规范的命名属性。兼容kebab命名风格属而的性；转换时将末尾的"_"移除。

    >>> to_dict()、make_dom()转换规则：
    >>> 1. camel、snake、pascal风格维持不变
    >>> 2. kebab风格转为snake
    >>> 3. 去掉末尾的"_"
    """

    def __init__(
        self,
        dom_class,
        **kwargs,
    ) -> None:
        self._make_dom = dom_class
        for [k, v] in kwargs.items():
            setattr(self, k, v)

    def to_dict(self):
        """归一属性命名，并将它们放入字典结构

        >>> 规则：
        >>> 1. camel、snake、pascal风格维持不变
        >>> 2. kebab风格转为snake
        >>> 3. 去掉末尾的"_"
        """

        d = _change_key_case(
            _user_define_properties_dict(self),
            (drop_ends_underline, snake_case_to_kebab),
        )
        return d

    def make_dom(self):
        """归一属性命名，并用它们构造tagic节点

        >>> 规则：
        >>> 1. camel、snake、pascal风格维持不变
        >>> 2. kebab风格转为snake
        >>> 3. 去掉末尾的"_"
        """

        d = self.to_dict()
        return self._make_dom(attr=d)


class SvgPath(PythonIdentifier):
    def __init__(self, **kwargs) -> None:
        super().__init__(tagic_path, **kwargs)


class SvgAttr(PythonIdentifier):
    def __init__(self, **kwargs) -> None:
        super().__init__(tagic_svg, **kwargs)


def svg(**kwargs):
    d = SvgAttr(**kwargs).to_dict()
    return tagic_svg(
        attr=d | d.pop("attr", {}),
    )


def path(**kwargs):
    return SvgPath(**kwargs).make_dom()
